package org.jiucheng.magpiebridge.manager.controller;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.time.DateUtils;
import org.jiucheng.ioc.annotation.Inject;
import org.jiucheng.magpiebridge.manager.dto.OAuth2GithubAccessTokenDto;
import org.jiucheng.magpiebridge.manager.dto.OAuth2GithubControlDto;
import org.jiucheng.magpiebridge.manager.dto.OAuth2GithubUserDto;
import org.jiucheng.magpiebridge.manager.entity.OAuth2Control;
import org.jiucheng.magpiebridge.manager.entity.SysUser;
import org.jiucheng.magpiebridge.manager.entity.SysUserServer;
import org.jiucheng.magpiebridge.manager.out.TplOut;
import org.jiucheng.magpiebridge.manager.service.IOAuth2ControlService;
import org.jiucheng.magpiebridge.manager.service.ISysUserService;
import org.jiucheng.magpiebridge.manager.util.FeignRequest;
import org.jiucheng.magpiebridge.manager.util.JwtUtil;
import org.jiucheng.plugin.db.IBaseService;
import org.jiucheng.util.StringUtil;
import org.jiucheng.web.annotation.Controller;
import org.jiucheng.web.annotation.Param;
import org.jiucheng.web.annotation.RequestMapping;
import org.jiucheng.web.annotation.RequestMethod;
import org.jiucheng.web.util.WebUtil;

import com.alibaba.fastjson.JSON;

import feign.Feign;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import feign.Retryer;

/**
 * 第三方授权登陆
 * 
 * @author jiucheng
 *
 */
@Controller
public class OAuth2CallbackController {
    
    @Inject
    private IBaseService baseService;
    @Inject
    private JwtUtil jwtUtil;
    @Inject
    private ISysUserService sysUserService;
    @Inject("OAuth2ControlService")
    private IOAuth2ControlService OAuth2ControlService;
    
    @RequestMapping(value = "/oauth2/goto", method = {RequestMethod.GET}, out = TplOut.class)
    public String oauth2(@Param("type") String type, HttpServletRequest req, HttpServletResponse res) throws IOException {
        if (StringUtil.isNotBlank(type)) {
            if (OAuth2Control.Category.GITHUB.equalsIgnoreCase(type)) {
            	OAuth2GithubControlDto githubControl = OAuth2ControlService.getOauth2GithubControlDto();
            	if (githubControl != null && "T".equalsIgnoreCase(githubControl.getOpened())) {
	                req.setAttribute("githubClientId", githubControl.getClientId());
	                req.setAttribute("githubCallback", githubControl.getCallback());
	                return "oauth2github";
            	}
            }
        }
        res.sendError(404);
        return null;
    }

    /**
     * 开源中国OAuth2登陆
     * 
     * @param code
     * @param state
     * @throws SQLException
     */
    @RequestMapping(value = "/oauth2/callback/oschina", method = {RequestMethod.GET})
    public void oschina(@Param("code") String code, @Param("state") String state) throws SQLException {
        // TODO 开源中国OAuth2登陆
        throw new UnsupportedOperationException();
    }
    
    /**
     * github OAuth2登陆
     * 
     * @param code
     * @param state
     * @throws SQLException
     */
    @RequestMapping(value = "/oauth2/callback/github", method = {RequestMethod.GET})
    public void github(@Param("code") String code, @Param("state") String state, HttpServletResponse resp) throws SQLException {
    	OAuth2GithubControlDto githubControl = OAuth2ControlService.getOauth2GithubControlDto();
    	if (githubControl == null || !"T".equalsIgnoreCase(githubControl.getOpened())) {
    		printResponse(resp, "GITHUB登陆，未开启~");
        	return;
    	}
        FeignRequest feignRequest = Feign.builder().retryer(Retryer.NEVER_RETRY).requestInterceptor(new RequestInterceptor() {
            public void apply(RequestTemplate template) {
                template.header("accept", "application/json");
            }
        }).target(FeignRequest.class,
                MessageFormat.format("https://github.com/login/oauth/access_token?client_id={0}&client_secret={1}&code={2}",
                		githubControl.getClientId(), githubControl.getClientSecret(), code));
        String res = feignRequest.get();
        final OAuth2GithubAccessTokenDto accessTokenDto = JSON.parseObject(res, OAuth2GithubAccessTokenDto.class);
        if (StringUtil.isBlank(accessTokenDto.getAccess_token())) {
            printResponse(resp, "授权失败~");
        	return;
        }
        feignRequest = Feign.builder().retryer(Retryer.NEVER_RETRY).requestInterceptor(new RequestInterceptor() {
            public void apply(RequestTemplate template) {
                template.header("Authorization", "token " + accessTokenDto.getAccess_token());
                template.header("accept", "application/json");
            }
        }).target(FeignRequest.class, "https://api.github.com/user");
        res = feignRequest.get();
        OAuth2GithubUserDto userDto = JSON.parseObject(res, OAuth2GithubUserDto.class);
        if (StringUtil.isBlank(userDto.getEmail())) {
            printResponse(resp, "邮箱不存在，授权失败~");
        	return;
        }
        SysUser sysUser = new SysUser();
        sysUser.setEmail(userDto.getEmail());
        List<SysUser> sysUsers = baseService.list(sysUser);
        if (sysUsers != null && !sysUsers.isEmpty()) {
            sysUser = sysUsers.get(0);
            // 账户是否停用
            if ("T".equals(sysUser.getInactive())) {
                printResponse(resp, "账号已停用");
            	return;
            }
        } else {
            sysUser.setPassword(StringUtil.EMPTY);
            sysUser.setIsSuper("F");
            
            SysUserServer sysUserServer = new SysUserServer();
            sysUserServer.setPortCount(0L);
            sysUserServer.setPortCountLimit(0L);
            sysUserServer.setSubCount(0L);
            sysUserServer.setServerId(0L);
            sysUserServer.setSubCountLimit(2L);
            sysUserServer.setVer(0);
            Long id = sysUserService.saveSysUser(sysUser, sysUserServer);
            sysUser.setId(id);
        }
        Map<String, String> claims = new HashMap<String, String>();
        claims.put("gid", Long.toString(sysUser.getId()));
        claims.put("gemail", sysUser.getEmail());
        claims.put("isSuper", sysUser.getIsSuper());
        try {
            String token = jwtUtil.genToken(claims, DateUtils.addYears(new Date(), 10));
            Cookie cookie = new Cookie("token", token);
            cookie.setPath("/");
            cookie.setMaxAge(-1);
            resp.addCookie(cookie);
            WebUtil.redirect("/index");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    private void printResponse(HttpServletResponse resp, String msg) {
        try {
            PrintWriter out = resp.getWriter();
            out.print(msg);
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
